#include "ustc_comdef.h"
#include "ustc_custom.h"
#include "ustc_api.h"
#include "ustc_usb_drv.h"
#include "ustc_usb_scsi.h"
#include "ustc_usb_bulk.h"

extern USB_PATH_T *gp_usb_path;

const STD_INQUIRYDATA_T scsi_inquiry_data =
{
    0x00,// RBC_DEVICE,:5
    0,//INT8 Reserved0 : 3;

    0,//INT8 Reserved1 : 7;
    1,//INT8 RemovableMedia : 1;

    2,//INT8 Reserved2;

    2,//INT8 Reserved3 : 5;
    0,//INT8 NormACA : 1;
    0,//INT8 Obsolete0 : 1;
    0,//INT8 AERC : 1;

    //INT8 Reserved4[3];
    {
        0x1F,0,0
    },

    0,//INT8 SoftReset : 1;
    0,//INT8 CommandQueue : 1;
	0,//INT8 Reserved5 : 1;
	0,//INT8 LinkedCommands : 1;
	0,//INT8 Synchronous : 1;
	0,//INT8 Wide16Bit : 1;
	0,//INT8 Wide32Bit : 1;
	0,//INT8 RelativeAddressing : 1;

    //INT8 VendorId[8];
    {
        'c','h','i','p',
        'n','u','t','s'
    },

	//INT8 ProductId[16];
    {
        'c','6','2','6',
    	'e',' ',' ',' ',
    	' ',' ',' ',' ',
    	' ',' ',' ',' '
    },

	//INT8 ProductRevisionLevel[4];
    {
        '0','.','0','0'
    },


//  Above is 36 bytes
//  can be tranmitted by Bulk



    //INT8 VendorSpecific[20]; out[64 bytes] within one packet only.
    {
        0, 0, 0, 0,
        0, 0, 0, 0,
        0, 0, 0, 0,
        0, 0, 0, 0,
        0, 0, 0, 0
    },


    0,//INT8 InfoUnitSupport : 1;
    0,//INT8 QuickArbitSupport : 1;
    0,//INT8 Clocking : 2;
    0,//INT8 Reserved1 : 4;
    0,//INT8  Reserved2 ;

    //USHORT VersionDescriptor[8] ;
    {
        0, 0, 0, 0,
        0, 0, 0, 0
    },


    //INT8 Reserved3[22];
    {
        0, 0, 0, 0,
        0, 0, 0, 0,
        0, 0, 0, 0,
        0, 0, 0, 0,
        0, 0, 0, 0,
        0, 0
    }

};

/* byte 3: capacity list length;byte4-byte7: number of blocks, byte 8:descriptor code; byte 9-11 block length
 16M =0x8000 *512 bytes
*/
 const USTC_U8	scsi_format_capacity[12] = {
		0x00,0x00,0x00,0x08,0x00,0x00,0x80,0x00,
		0x03,0x00,0x02,0x00
	};

/* byte 0-3: last logical block address(msb->lsb); byte 4-7: block length in bytes(msb->lsb)
2M =0x1000*512 bytes
*/
const READ_CAPACITY_DATA_T	scsi_disk_capacity = {
		0x00,0x00,0x0f,0xff,0x00,0x00,0x02,0x00
	};

const unsigned char scsi_mode_sense_data[4] = {0x03,0x00,0x00,0x00};

/*cdrom support*/
const unsigned char scsi_mode_sense10_data[8] = {0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char scsi_read_toc_data[12] = {
		0x00,0x12,0x01,0x01,
		0x00,0x14,0x01,0x00,
		0x00,0x00,0x02,0x00};

/*

*/
void scsi_check_disk_src(USTC_U8 lun)
{
	if (lun < gp_usb_path->p_para_usb->udisk_disk_num[0])//SD card
	{
		gp_usb_path->udisk_disk_src = 0;
		gp_usb_path->udisk_disk_index = lun;
	}
	else if (lun < (gp_usb_path->p_para_usb->udisk_disk_num[0]+gp_usb_path->p_para_usb->udisk_disk_num[1]))//nans flash
	{
		gp_usb_path->udisk_disk_src = 1;
		gp_usb_path->udisk_disk_index = lun - gp_usb_path->p_para_usb->udisk_disk_num[0] ;
	}
	else if (lun < (gp_usb_path->p_para_usb->udisk_disk_num[0]+gp_usb_path->p_para_usb->udisk_disk_num[1]+gp_usb_path->p_para_usb->udisk_disk_num[2]))//host-udisk
	{
		gp_usb_path->udisk_disk_src = 2;
		gp_usb_path->udisk_disk_index = lun - gp_usb_path->p_para_usb->udisk_disk_num[0] - gp_usb_path->p_para_usb->udisk_disk_num[1];
	}
	
}

int scsi_handler(void)
{
	//guosheng
	if(g_ustc_usb_contorl.sys_startmode==0)
	{
		scsi_check_disk_src(gp_usb_path->bulk_hdr.cbw.bCBW_LUN);
	}
	else
	{
		gp_usb_path->udisk_disk_src = 0;
		gp_usb_path->udisk_disk_index = 0;
	}
	switch(gp_usb_path->bulk_hdr.cbw.cdb.Cdb_Generic.OperationCode)
	{
		case SPC_CMD_INQUIRY:
			spc_inquiry();
			break;
		case SPC_CMD_READLONG:
			spc_read_format_capacities();
			break;
		case RBC_CMD_READCAPACITY:
			rbc_read_capacity();
			break;
		case RBC_CMD_READ10:
		case RBC_CMD_TEST:
			spc_read10();
			break;
		case RBC_CMD_WRITE10:
			spc_write10();
			break;
		case RBC_CMD_VERIFY10:
			spc_verify10();
			break;
		case SPC_CMD_MODESENSE6:
			spc_mode_sense6();
			break;
		case SPC_CMD_MODESENSE10:
			spc_mode_sense10();
			break;
		case SPC_CMD_TESTUNITREADY:
			spc_test_unit_ready();
			break;
		case SPC_CMD_REQUESTSENSE:
			break;
		case SPC_CMD_PRVENTALLOWMEDIUMREMOVAL:
			spc_prevent_remove();
			break;
		case VENDOR_CMD_GET_INFO:
			vendor_get_info();
			break;
		case VENDOR_CMD_SET_INFO:
			vendor_set_info();
			break;
		case VENDOR_CMD_GET_VER:
			vendor_get_ver();
			break;
		case SPC_CMD_READTOC:
			spc_read_toc();
			break;
		default:
			bulk_set_csw_status(CASECMDFAIL,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
			gp_usb_path->bot_state = BOTFSM_CSW;
			break;
	}	
	return 0;
}

//return 0 success
int spc_inquiry(void)
{
	int retval =0;
	STD_INQUIRYDATA_T *p_inquiry;
	
	if(gp_usb_path->bulk_hdr.cbw.cdb.Spc_Inquiry.EnableVPD)
	{
		switch(gp_usb_path->bulk_hdr.cbw.cdb.Spc_Inquiry.PageCode)
		{
			case VPDPAGE_SERIAL_NUMBER:
				//bot_data =(PUSTC_U8) &SerialPage;
				//bot_len = sizeof(VPD_SERIAL_PAGE);
				//break;
			case VPDPAGE_DEVICE_IDENTITY:
				//bot_data = (PUSTC_U8)&DeviceIDPage;
				//bot_len = sizeof(VPD_DEVICE_ID_PAGE);
				//break;
			default:
				bulk_set_csw_status(CASECMDFAIL,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
				//RBC_BuildSenseData(SCSI_SENSE_ILLEGAL_REQUEST,SCSI_ADSENSE_ILLEGAL_COMMAND,0x00);
				gp_usb_path->bot_state = BOTFSM_CSW;
				return 1;
		}
	}
	else if(gp_usb_path->bulk_hdr.cbw.cdb.Spc_Inquiry.CmdSupportData)
	{
		bulk_set_csw_status(CASECMDFAIL,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
		gp_usb_path->bot_state = BOTFSM_CSW;
		return 1;
	}
	else
	{
       	gp_usb_path->bot_data =(USTC_U8 *) gp_usb_path->usb_cache;
		ustc_memcpy(gp_usb_path->bot_data,(const void*)&scsi_inquiry_data,sizeof(STD_INQUIRYDATA_T));
		p_inquiry = (STD_INQUIRYDATA_T*)gp_usb_path->bot_data;
		ustc_memcpy((void*)p_inquiry->VendorId,gp_usb_path->p_para_usb->udisk_vendor,8);
		ustc_memcpy((void*)p_inquiry->ProductId,gp_usb_path->p_para_usb->udisk_product,16);
		
		gp_usb_path->bot_len = sizeof(STD_INQUIRYDATA_T);
		gp_usb_path->bot_len_transfer =0;
#ifdef AP_USB_FIXBUG
		gp_usb_path->usb_sec_num=0;//guosheng
#endif
		//support identify as cdrom type
		if (gp_usb_path->p_para_usb->udisk_disk_flag[4*gp_usb_path->udisk_disk_src + gp_usb_path->udisk_disk_index] & 4)
		{
			gp_usb_path->usb_cache[0] = 0x05;
		}
	}

	
	if( gp_usb_path->bot_len > gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen )
	{
		gp_usb_path->bot_len = gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen;
		gp_usb_path->bot_len_transfer =0;
		bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	}
	else if ( gp_usb_path->bot_len == gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen )
	{
		bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	}
	else
	{
		bulk_set_csw_status(CASE5,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	}

	gp_usb_path->bot_state = BOTFSM_DATAIN;

	return retval;
}


	
int spc_read_format_capacities(void)
{
	USTC_U32 block_number = 0;

	if (0 == g_ustc_usb_contorl.sys_startmode)
	{
		block_number = gp_usb_path->p_para_usb->udisk_disk_size[gp_usb_path->udisk_disk_src*4 + gp_usb_path->udisk_disk_index];
	}
	else
	{
		block_number = 0;
	}
	//fill structure
	//using usb_cache as temperaly buffer; because FormatCapacity is const array,can't modify
	ustc_memcpy(gp_usb_path->usb_cache,scsi_format_capacity,sizeof(scsi_format_capacity));

	gp_usb_path->usb_cache[4] = (USTC_U8)((block_number&0xff000000)>>24);
	gp_usb_path->usb_cache[5] = (USTC_U8)((block_number&0x00ff0000)>>16);
	gp_usb_path->usb_cache[6] = (USTC_U8)((block_number&0x0000ff00)>>8);
	gp_usb_path->usb_cache[7] = (USTC_U8)(block_number&0x000000ff);
	
	
	gp_usb_path->bot_data =(USTC_U8 *) gp_usb_path->usb_cache;
	gp_usb_path->bot_len = sizeof(scsi_format_capacity);
	gp_usb_path->bot_len_transfer =0;
#ifdef AP_USB_FIXBUG
	gp_usb_path->usb_sec_num=0;//guosheng
#endif
	bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	gp_usb_path->bot_state = BOTFSM_DATAIN;
	return 0;
}

int rbc_read_capacity(void)
{
	READ_CAPACITY_DATA_T *p;
	USTC_U32 block_number = 0;

	if (0 == g_ustc_usb_contorl.sys_startmode)
	{
		block_number = gp_usb_path->p_para_usb->udisk_disk_size[gp_usb_path->udisk_disk_src*4 + gp_usb_path->udisk_disk_index];
		block_number -=1;
	}
	else
	{
		block_number = 0;
	}
	
	//using usb_cache as temperaly buffer; because FormatCapacity is const array,can't modify
	ustc_memcpy(gp_usb_path->usb_cache,(const void*)&scsi_disk_capacity,sizeof(READ_CAPACITY_DATA_T));

	//fill structure
	p = (READ_CAPACITY_DATA_T *)gp_usb_path->usb_cache;
	p->LBA_3 = (USTC_U8)((block_number&0xff000000)>>24);
	p->LBA_2 = (USTC_U8)((block_number&0x00ff0000)>>16);
	p->LBA_1 = (USTC_U8)((block_number&0x0000ff00)>>8);
	p->LBA_0 = (USTC_U8)(block_number&0x000000ff);

	gp_usb_path->bot_data =(USTC_U8 *)gp_usb_path->usb_cache;
	gp_usb_path->bot_len = sizeof(READ_CAPACITY_DATA_T);
	gp_usb_path->bot_len_transfer =0;
#ifdef AP_USB_FIXBUG
	gp_usb_path->usb_sec_num=0;//guosheng
#endif
	bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	gp_usb_path->bot_state = BOTFSM_DATAIN;
	return 0;
}

int spc_read10(void)
{
	int retval =0;
	
	gp_usb_path->usb_start_lba = gp_usb_path->bulk_hdr.cbw.cdb.Spc_Read.LBA.LBA_W8.LBA_3;
	gp_usb_path->usb_start_lba = (gp_usb_path->usb_start_lba <<8) | gp_usb_path->bulk_hdr.cbw.cdb.Spc_Read.LBA.LBA_W8.LBA_2;
	gp_usb_path->usb_start_lba = (gp_usb_path->usb_start_lba <<8) | gp_usb_path->bulk_hdr.cbw.cdb.Spc_Read.LBA.LBA_W8.LBA_1;
	gp_usb_path->usb_start_lba = (gp_usb_path->usb_start_lba <<8) | gp_usb_path->bulk_hdr.cbw.cdb.Spc_Read.LBA.LBA_W8.LBA_0;
	gp_usb_path->usb_sec_off = 0;
	gp_usb_path->usb_sec_num   = gp_usb_path->bulk_hdr.cbw.cdb.Spc_Read.transfer_len_hi;
	gp_usb_path->usb_sec_num   = (gp_usb_path->usb_sec_num <<8) | gp_usb_path->bulk_hdr.cbw.cdb.Spc_Read.transfer_len_lo;
	gp_usb_path->usb_sec_num   &= 0xffff;
	
	gp_usb_path->bot_len = gp_usb_path->usb_sec_num * 512;
	gp_usb_path->bot_len_transfer =0;
	
	if( gp_usb_path->bot_len > gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen )
	{
		gp_usb_path->bot_len = gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen;
		gp_usb_path->bot_len_transfer =0;
		bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	}
	else if ( gp_usb_path->bot_len == gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen )
	{
		bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	}
	else
	{
		bulk_set_csw_status(CASE5,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	}
	gp_usb_path->bot_state = BOTFSM_DATAIN;
	return retval;
}	

int spc_mode_sense6(void)
{
	//using usb_cache as temperaly buffer; because FormatCapacity is const array,can't modify
	ustc_memcpy(gp_usb_path->usb_cache,(const void*)&scsi_mode_sense_data,sizeof(scsi_mode_sense_data));

	if (gp_usb_path->p_para_usb->udisk_disk_flag[gp_usb_path->udisk_disk_src*4+gp_usb_path->udisk_disk_index] & 1)//write protected
		gp_usb_path->usb_cache[2] = 0x80;
	
	gp_usb_path->bot_data =(USTC_U8 *)gp_usb_path->usb_cache;
	gp_usb_path->bot_len = sizeof(scsi_mode_sense_data);
	gp_usb_path->bot_len_transfer =0;
	bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	gp_usb_path->bot_state = BOTFSM_DATAIN;
	return 0;	
}

int spc_mode_sense10(void)
{
	//using usb_cache as temperaly buffer; because FormatCapacity is const array,can't modify
	ustc_memcpy(gp_usb_path->usb_cache,(const void*)&scsi_mode_sense10_data,sizeof(scsi_mode_sense10_data));

	gp_usb_path->bot_data =(USTC_U8 *)gp_usb_path->usb_cache;
	gp_usb_path->bot_len = sizeof(scsi_mode_sense10_data);
	gp_usb_path->bot_len_transfer =0;
	bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	gp_usb_path->bot_state = BOTFSM_DATAIN;
	return 0;	
}
int spc_read_toc(void)
{
	//using usb_cache as temperaly buffer; because FormatCapacity is const array,can't modify
	ustc_memcpy(gp_usb_path->usb_cache,(const void*)&scsi_read_toc_data,sizeof(scsi_read_toc_data));

	gp_usb_path->bot_data =(USTC_U8 *)gp_usb_path->usb_cache;
	gp_usb_path->bot_len = sizeof(scsi_read_toc_data);
	gp_usb_path->bot_len_transfer =0;
	bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	gp_usb_path->bot_state = BOTFSM_DATAIN;
	return 0;	
}


int spc_write10(void)
{
	int retval =0;
	
	gp_usb_path->usb_start_lba = gp_usb_path->bulk_hdr.cbw.cdb.Spc_Write.LBA.LBA_W8.LBA_3;
	gp_usb_path->usb_start_lba =(gp_usb_path->usb_start_lba <<8) | gp_usb_path->bulk_hdr.cbw.cdb.Spc_Write.LBA.LBA_W8.LBA_2;
	gp_usb_path->usb_start_lba =(gp_usb_path->usb_start_lba <<8) | gp_usb_path->bulk_hdr.cbw.cdb.Spc_Write.LBA.LBA_W8.LBA_1;
	gp_usb_path->usb_start_lba =(gp_usb_path->usb_start_lba <<8) | gp_usb_path->bulk_hdr.cbw.cdb.Spc_Write.LBA.LBA_W8.LBA_0;
	gp_usb_path->usb_sec_off = 0;
	gp_usb_path->usb_sec_num   = gp_usb_path->bulk_hdr.cbw.cdb.Spc_Write.transfer_len_hi;
	gp_usb_path->usb_sec_num   =(gp_usb_path->usb_sec_num <<8) | gp_usb_path->bulk_hdr.cbw.cdb.Spc_Write.transfer_len_lo;
	gp_usb_path->usb_sec_num   &= 0xffff;
	
	gp_usb_path->bot_len = gp_usb_path->usb_sec_num * 512;
	gp_usb_path->bot_len_transfer =0;
	
	if( gp_usb_path->bot_len > gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen )
	{
		gp_usb_path->bot_len = gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen;
		gp_usb_path->bot_len_transfer =0;
		bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	}
	else if ( gp_usb_path->bot_len == gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen )
	{
		bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	}
	else
	{
		bulk_set_csw_status(CASE5,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	}
	gp_usb_path->bot_state = BOTFSM_DATAOUT;

	//for write multi_block
	if (gp_usb_path->usb_sec_num >MAX_CACHE_BLOCK)
		gp_usb_path->sec_num = MAX_CACHE_BLOCK;
	else
		gp_usb_path->sec_num = gp_usb_path->usb_sec_num;
	
	return retval;
}	

//default is OK?
int spc_test_unit_ready()
{
	bulk_set_csw_status(CASEOK,0);
	gp_usb_path->bot_state = BOTFSM_CSW;
	return 0;
}

int spc_verify10()
{
	bulk_set_csw_status(CASEOK,0);
	gp_usb_path->bot_state = BOTFSM_CSW;
	return 0;
}

int spc_prevent_remove()
{
	bulk_set_csw_status(CASEOK,0);
	gp_usb_path->bot_state = BOTFSM_CSW;
	return 0;
}

int vendor_get_info(void)
{
	USTC_U8 disktype;
	USTC_U8 cmdclass;
	int i;

	#if 0
	disktype = gp_usb_path->bulk_hdr.cbw.cdb.vendor_get_info.subcmd;
	gp_usb_path->udisk_disk_src = disktype;
	
	//check, if no isector, fill zero	
	if (gp_usb_path->p_para_usb->isector[disktype] ==0)
	{
		ustc_memset(gp_usb_path->usb_cache,0,512);
		for (i=0;i<gp_usb_path->p_para_usb->udisk_disk_num[disktype];i++)
		{
			*((USTC_U32*)(gp_usb_path->usb_cache + 0x80)) = gp_usb_path->p_para_usb->udisk_disk_start[disktype*4];		
			*((USTC_U32*)(gp_usb_path->usb_cache + 0x84)) = gp_usb_path->p_para_usb->udisk_disk_size[disktype*4];
		}	
	}
	else
	{
		if (gp_usb_path->udisk_disk_src ==0)//sd
			sd_read_multi_block(gp_usb_path->usb_cache,(unsigned int)gp_usb_path->p_para_usb->isector[disktype],1);
		else
			ftl_read_sector(gp_usb_path->usb_cache,(unsigned int)gp_usb_path->p_para_usb->isector[disktype],1);
	}
		

	gp_usb_path->bot_data =(USTC_U8 *)gp_usb_path->usb_cache;
	gp_usb_path->bot_len = 512;
	gp_usb_path->bot_len_transfer =0;
	bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	gp_usb_path->bot_state = BOTFSM_DATAIN;
	return 0;
	#endif
	
	cmdclass = gp_usb_path->bulk_hdr.cbw.cdb.vendor_get_info.cmdclass;
	if (cmdclass == USB_BOOT)
	{
		gp_usb_path->bot_len = gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen;
		if (gp_usb_path->bot_len > 0)
		{

			if (gp_usb_path->bulk_hdr.cbw.cdb.vendor_get_info.info_type == BOOT_ACCESS_HALFWORD)//half-word access
			{
				gp_usb_path->bulk_hdr.cbw.cdb.vendor_get_info.address &= 0xfffffffe;
			}
			else if (gp_usb_path->bulk_hdr.cbw.cdb.vendor_get_info.info_type == BOOT_ACCESS_LONG)//word access
			{
				gp_usb_path->bulk_hdr.cbw.cdb.vendor_get_info.address &= 0xfffffffc;
			}
		
			bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
			gp_usb_path->bot_data = (USTC_U8*)(gp_usb_path->bulk_hdr.cbw.cdb.vendor_get_info.address);
			gp_usb_path->bot_state = BOTFSM_DATAIN;
			//g_udisk->pre_bot_state = BOTFSM_CBW;
			gp_usb_path->bot_len_transfer=0;
			//gp_usb_path->vendor_flag=1;	
#ifdef AP_USB_FIXBUG
			gp_usb_path->usb_sec_num=0;//guosheng
#endif

			ustc_delay(1);
		}
		else
		{
			bulk_set_csw_status(CASEOK,0);
			gp_usb_path->bot_state = BOTFSM_CSW;
			//g_udisk->pre_bot_state = BOTFSM_CBW;
		}
	}
	else if(cmdclass == USB_SECURITY)
	{
		disktype = gp_usb_path->bulk_hdr.cbw.cdb.vendor_get_info.subcmd;
		gp_usb_path->udisk_disk_src = disktype;
		
		//check, if no isector, fill zero	
		if (gp_usb_path->p_para_usb->isector[disktype] ==0)
		{
			ustc_memset(gp_usb_path->usb_cache,0,512);
			for (i=0;i<gp_usb_path->p_para_usb->udisk_disk_num[disktype];i++)
			{
				*((USTC_U32*)(gp_usb_path->usb_cache + 0x80)) = gp_usb_path->p_para_usb->udisk_disk_start[disktype*4];		
				*((USTC_U32*)(gp_usb_path->usb_cache + 0x84)) = gp_usb_path->p_para_usb->udisk_disk_size[disktype*4];
			}	
		}
		else
		{
			gp_usb_path->p_para_usb->read[0]((USTC_U32*)gp_usb_path->usb_cache,(unsigned int)gp_usb_path->p_para_usb->isector[disktype],1);
		}


		gp_usb_path->bot_data =(USTC_U8 *)gp_usb_path->usb_cache;
		gp_usb_path->bot_len = 512;
		gp_usb_path->bot_len_transfer =0;
		bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
		gp_usb_path->bot_state = BOTFSM_DATAIN;
	}

	return 0;
}
#if 0
void process_usbboot_cmd(USTC_U8 cmd_index, USTC_U8 para,USTC_U32 addr,USTC_U32 val)
{
	switch (cmd_index)
	{
		case BOOT_WRITE_SINGLE://write single
			if (para ==BOOT_ACCESS_BYTE)//byte access
			{
				*(USTC_U8 *)addr = val & 0xff;
			}
			else if (para ==BOOT_ACCESS_HALFWORD)//half-word access
			{
				addr = addr & 0xfffffffe;
				*(USTC_U16 *)addr = val & 0xffff;
			}
			else//word access
			{
				addr = addr & 0xfffffffc;
				*(USTC_U32 *)addr = val;
			}
			break;
		case BOOT_LOAD://load, process in Bulk_DataOutHandler()
			break;
		case BOOT_TEST://test
			break;
		case BOOT_DO://do, defer to complete this bulk only transfer(after CSW)
			g_fw.sys_para.usb_control.exec_flag = 1;
			break;
		case BOOT_RUN://run, defer to complete this bulk only transfer(after CSW)
			g_fw.sys_para.usb_control.exec_flag = 2;
			break;
		default:
			break;
	}
}
#endif
int vendor_set_info(void)
{
	USTC_U8 disktype;
	USTC_U8 cmdclass;
	//int i;

	#if 0	
	disktype = gp_usb_path->bulk_hdr.cbw.cdb.vendor_get_info.subcmd;
	gp_usb_path->udisk_disk_src = disktype;
	
	gp_usb_path->bot_data =(USTC_U8 *)gp_usb_path->usb_cache;
	gp_usb_path->bot_len = 512;
	gp_usb_path->bot_len_transfer =0;
	bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	gp_usb_path->bot_state = BOTFSM_DATAOUT;
	#endif

	cmdclass = gp_usb_path->bulk_hdr.cbw.cdb.vendor_set_info.cmdclass;

	if (cmdclass == USB_BOOT)
	{
		gp_usb_path->bot_len = gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen;
		if (gp_usb_path->bot_len > 0)/*command with data phase from usb host*/
		{
			if (gp_usb_path->bulk_hdr.cbw.cdb.vendor_set_info.info_type == BOOT_ACCESS_HALFWORD)//half-word access
			{
				gp_usb_path->bulk_hdr.cbw.cdb.vendor_set_info.address &= 0xfffffffe;
			}
			else if (gp_usb_path->bulk_hdr.cbw.cdb.vendor_set_info.info_type == BOOT_ACCESS_LONG)//word access
			{
				gp_usb_path->bulk_hdr.cbw.cdb.vendor_set_info.address &= 0xfffffffc;
			}
#ifdef AP_USB_FIXBUG
			gp_usb_path->bot_data=(USTC_U8 *)(gp_usb_path->bulk_hdr.cbw.cdb.vendor_set_info.address);
#endif			
			bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
			gp_usb_path->bot_state = BOTFSM_DATAOUT;
			//g_udisk->pre_bot_state= BOTFSM_CBW;
			//g_udisk->vendor_flag=1;
			gp_usb_path->bot_len_transfer = 0;
#ifdef AP_USB_FIXBUG
			gp_usb_path->usb_sec_num = 0;//for debug, should modify bulk process usb_bulk_process()
#endif
			//g_fw.usb->usb_sec_num = 1;//for debug, should modify bulk process usb_bulk_process()
		}
		else /*commands without data phase*/
		{
			/*process command*/
#if 0
			process_usbboot_cmd(gp_usb_path->bulk_hdr.cbw.cdb.vendor_set_info.subcmd,
					gp_usb_path->bulk_hdr.cbw.cdb.vendor_set_info.info_type,
					gp_usb_path->bulk_hdr.cbw.cdb.vendor_set_info.address,
					gp_usb_path->bulk_hdr.cbw.cdb.vendor_set_info.value);
#endif		
			bulk_set_csw_status(CASEOK,0);
			//g_udisk->vendor_flag=0;
			gp_usb_path->bot_state = BOTFSM_CSW;
			//g_udisk->pre_bot_state = BOTFSM_CBW;
		}
	}
	else
	{
		disktype = gp_usb_path->bulk_hdr.cbw.cdb.vendor_get_info.subcmd;
		gp_usb_path->udisk_disk_src = disktype;
		
		gp_usb_path->bot_data =(USTC_U8 *)gp_usb_path->usb_cache;
		gp_usb_path->bot_len = 512;
		gp_usb_path->bot_len_transfer =0;
		bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
		gp_usb_path->bot_state = BOTFSM_DATAOUT;
	}

	return 0;

}

/*get hw/fw version*/
int vendor_get_ver(void)
{
	USTC_U32* ptr;
//	T_PATCH_VERSION patch_version_func;
	
	//fill structure
	ptr = (USTC_U32*)gp_usb_path->usb_cache;
	ustc_memset(ptr,0,0x40);

	gp_usb_path->bot_data =(USTC_U8 *)gp_usb_path->usb_cache;
	gp_usb_path->bot_len = 0x40;
	gp_usb_path->bot_len_transfer =0;
	bulk_set_csw_status(CASE6,gp_usb_path->bulk_hdr.cbw.dCBW_DataXferLen);
	gp_usb_path->bot_state = BOTFSM_DATAIN;
	return 0;
}
